﻿using MockDataAccess;
using MockDataTransferObject;
using System;
using System.Collections.Generic;
using MockCommon;
using System.Collections.ObjectModel;

namespace MockBusiness
{
    public class MessageBusiness
    {
        #region Initialize
        private static MessageBusiness _instance;
        private readonly UserDataAccess _userDataAccess;
        private readonly MessageDataAccess _messageDataAccess;

        /// <summary>
        /// Gets the user data test.
        /// </summary>
        public Collection<User> UserDataTest
        {
            get
            {
                return _userDataAccess.AffectedRows;
            }
        }

        /// <summary>
        /// Gets the message data test.
        /// </summary>
        public Collection<Message> MessageDataTest
        {
            get
            {
                return _messageDataAccess.AffectedRows;
            }
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="MessageBusiness"/> class from being created.
        /// </summary>
        private MessageBusiness()
        {
            _messageDataAccess = new MessageDataAccess();
            _userDataAccess = new UserDataAccess();
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="MessageBusiness"/> class from being created.
        /// </summary>
        /// <param name="isFake">if set to <c>true</c> [is fake].</param>
        private MessageBusiness(bool isFake)
        {
            _messageDataAccess = new MessageDataAccess(isFake);
            _userDataAccess = new UserDataAccess(isFake);
        }

        /// <summary>
        /// Retrieves the instance.
        /// </summary>
        /// <returns></returns>
        public static MessageBusiness RetrieveInstance()
        {
            if (_instance == null)
                _instance = new MessageBusiness();
            return _instance;
        }

        /// <summary>
        /// Retrieves the instance.
        /// </summary>
        /// <param name="isFake">if set to <c>true</c> [is fake].</param>
        /// <returns></returns>
        public static MessageBusiness RetrieveInstance(bool isFake)
        {
            if (_instance == null)
                _instance = new MessageBusiness(isFake);
            return _instance;
        }
        #endregion

        #region CUD
        /// <summary>
        /// Inserts the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Insert(Message message)
        {
            if (message == null)
            {
                throw new MockException("Message is null", "Business");
            }
            if (_messageDataAccess.Exist(message.MessageId))
            {
                throw new MockException("Message id was existed", "Business");
            }
            User fromUser = message.From;
            if (fromUser == null)
            {
                throw new MockException("From user is null", "Business");
            }
            if (!_userDataAccess.Exist(fromUser.UserId))
            {
                throw new MockException("From user was not existed", "Business");
            }
            User toUser = message.To;
            if (toUser == null)
            {
                throw new MockException("To user is null", "Business");
            }
            if (!_userDataAccess.Exist(toUser.UserId))
            {
                throw new MockException("To user was not existed", "Business");
            }
            if (String.IsNullOrEmpty(message.Title))
            {
                throw new MockException("Title is required", "Business");
            }
            if (String.IsNullOrEmpty(message.Content))
            {
                throw new MockException("Content is required", "Business");
            }
            _messageDataAccess.Create(message);
        }

        /// <summary>
        /// Updates the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Update(Message message)
        {
            if (message == null)
            {
                throw new MockException("Message is null", "Business");
            }
            if (!_messageDataAccess.Exist(message.MessageId))
            {
                throw new MockException("Message id was not existed", "Business");
            }
            User fromUser = message.From;
            if (fromUser == null)
            {
                throw new MockException("From user is null", "Business");
            }
            if (!_userDataAccess.Exist(fromUser.UserId))
            {
                throw new MockException("From user was not existed", "Business");
            }
            User toUser = message.To;
            if (toUser == null)
            {
                throw new MockException("To user is null", "Business");
            }
            if (!_userDataAccess.Exist(toUser.UserId))
            {
                throw new MockException("To user was not existed", "Business");
            }
            if (String.IsNullOrEmpty(message.Title))
            {
                throw new MockException("Title is required", "Business");
            }
            if (String.IsNullOrEmpty(message.Content))
            {
                throw new MockException("Content is required", "Business");
            }
            _messageDataAccess.Update(message);
        }

        /// <summary>
        /// Updates the receive all.
        /// </summary>
        /// <param name="userId">The user id.</param>
        public void UpdateReceiveAll(Guid userId)
        {
            Collection<Message> messages = _messageDataAccess.GetByUserIdAndIsReceive(userId, false);
            foreach (Message message in messages)
            {
                message.IsReceive = true;
                _messageDataAccess.Update(message);
            }
        }
        #endregion

        #region R
        /// <summary>
        /// Gets the by id.
        /// </summary>
        /// <param name="messageId">The message id.</param>
        /// <returns></returns>
        public Message GetById(object messageId)
        {
            return _messageDataAccess.GetById(messageId);
        }

        /// <summary>
        /// Gets all by user id.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <returns></returns>
        public Collection<Message> GetAllByUserId(Guid userId)
        {
            return _messageDataAccess.GetByToUserId(userId);
        }

        /// <summary>
        /// Gets the count message.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <param name="isReceive">if set to <c>true</c> [is receive].</param>
        /// <returns></returns>
        public int GetCountMessage(Guid userId, bool isReceive)
        {
            return _messageDataAccess.GetCountByUserIdAndIsReceive(userId, isReceive);
        }

        /// <summary>
        /// Gets the top message.
        /// </summary>
        /// <param name="userId">The user id.</param>
        /// <param name="top">The top.</param>
        /// <returns></returns>
        public Collection<Message> GetTopMessage(Guid userId, int top)
        {
            return _messageDataAccess.GetTopByUserId(userId, top);
        }
        #endregion
    }
}
